package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.constants.user.UserRelationConstants;
import com.heima.common.exception.CustomException;
import com.heima.feigns.ArticleFeign;
import com.heima.feigns.BehaviorFeign;
import com.heima.model.article.dtos.StatisticsDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.service.StatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author lwh
 * @create 2021-10-12
 */
@Service
public class StatisticsServiceImpl implements StatisticsService {
    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private BehaviorFeign behaviorFeign;

    @Override
    public ResponseResult news(Long stime, Long etime) {
        WmUser user = WmThreadLocalUtils.getUser();
        //查询作者id
        ResponseResult<ApAuthor> result = articleFeign.findAuthorByUserId(user.getId());
        if (result.getCode() != 0) {
            throw new CustomException(AppHttpCodeEnum.SERVER_ERROR);
        }
        ApAuthor apAuthor = result.getData();
        if (apAuthor == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "没有查询到作者");
        }
        //查询统计数据的
        StatisticsDto dto = new StatisticsDto();
        dto.setStime(stime);
        dto.setEtime(etime);
        dto.setAuthorId(apAuthor.getId().toString());
        Map map = articleFeign.statisticsNews(dto);
        if (map == null || map.size() == 0) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "没有查询到统计数据");
        }

        //封装前端需要的格式的数据
        //          { value: 31, name: "文章量" },
        //          { value: 36, name: "阅读量" },
        //          { value: 15, name: "粉丝阅读量" },
        //          { value: 25, name: "评论量" },
        List<Map> list = new ArrayList<>();
        //文章数
        Map<String, Object> articleNumMap = new HashMap<>();
        articleNumMap.put("value", map.get("articleNum"));
        articleNumMap.put("name", "文章量");
        list.add(articleNumMap);
        //阅读量
        Map<String, Object> viewMap = new HashMap<>();
        viewMap.put("value", map.get("readNum"));
        viewMap.put("name", "阅读量");
        list.add(viewMap);

        //粉丝数待完成
        //先从redis中，查询出该作者的所有粉丝
        ZSetOperations opsForZSet = redisTemplate.opsForZSet();
        //拿到自己的所有粉丝
        Set<String> set = opsForZSet.range(UserRelationConstants.FANS_LIST + apAuthor.getId(), 0, -1);
        //查询自己的所有文章
        ResponseResult<List<ApArticle>> articleListResult = articleFeign.findArticleByAuthorId(apAuthor.getId().toString());
        if (articleListResult.getCode() != 0) {
            throw new CustomException(AppHttpCodeEnum.SERVER_ERROR, "查询作者文章fegin出错");
        }
        List<ApArticle> articleList = articleListResult.getData();
        if (articleList == null || articleList.size() == 0) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "没有查询到你的文章");
        }
        //遍历所有的文章
        int count = 0;//粉丝阅读量
        for (ApArticle apArticle : articleList) {
            //应该是拿着文章的id和粉丝的id，去mongdb的read集合里查询阅读的次数，最后累加
            for (String fansId : set) {
                ResponseResult readCount = behaviorFeign.findReadCount(String.valueOf(apArticle.getId()), fansId);
                if (readCount.getCode() != 0) {
                    throw new CustomException(AppHttpCodeEnum.SERVER_ERROR, "查询MongoDB出错");
                }
                Integer data = (Integer) readCount.getData();
                count = count + data;
            }
        }
        //粉丝阅读量
        Map<String, Object> fansReadMap = new HashMap<>();
        fansReadMap.put("value", count);
        fansReadMap.put("name", "粉丝阅读量");
        list.add(fansReadMap);

        //评论量
        Map<String, Object> commentNumMap = new HashMap<>();
        commentNumMap.put("value", map.get("commentNum"));
        commentNumMap.put("name", "评论量");
        list.add(commentNumMap);


        //***************开始处理页面table需要的数据*********************************//
        //第二部分表格的数据,意思显示选择的时间段里的每一天的数据
        //如果第一次,不传入时间,就查询全部,按照天分组
        List<Map<String, Object>> newsByDayList = (List<Map<String, Object>>) map.get("newsByDayList");
        //封装table需要的数据,这里还没有粉丝阅读量,需要在里面的每一个map中加入粉丝的阅读数量

        for (Map<String, Object> stringObjectMap : newsByDayList) {
            //计算这个日期的粉丝读数
            int countRead = 0;
            //先获取到日期
            String date = (String) stringObjectMap.get("date");
            //然后根据日期和作者去查询所以的文章
            List<ApArticle> apArticles = articleFeign.findApArticleByDateAndAuthorId(date, String.valueOf(apAuthor.getId()));
            //然后遍历所有的文章,再在里面遍历所有的粉丝,去统计粉丝的阅读次数

            for (ApArticle apArticle : apArticles) {
                for (String fansID : set) {
                    ResponseResult readCount = behaviorFeign.findReadCount(String.valueOf(apArticle.getId()), fansID);
                    if (readCount.getCode() != 0) {
                        throw new CustomException(AppHttpCodeEnum.SERVER_ERROR, "查询MongoDB出错");
                    }
                    Integer data = (Integer) readCount.getData();
                    countRead = countRead + data;
                }
            }
            //添加粉丝阅读数进去
            stringObjectMap.put("fanReadNum",countRead);
        }
        //构造table需要的数据
        Map tableDataMap = new HashMap();
        tableDataMap.put("tableData", newsByDayList);
        list.add(tableDataMap);

        return ResponseResult.okResult(list);
    }
}
